package cn.hbads.support.log;

import ch.qos.logback.classic.LoggerContext;
import cn.hbads.support.context.SpringContextHolder;
import cn.hutool.core.map.WeakConcurrentMap;
import cn.hutool.core.text.CharSequenceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;

import java.util.Map;


/**
 * @author : yvvb
 * @className : LogUtil
 * @date : 2025/4/17
 * @apiNote 日志输出工具类
 */
public final class LogUtil {
    private LogUtil() {
    }

    private static final Map<String, Logger> LOGGER_CACHE = new WeakConcurrentMap<>();

    public static void setLevel(Class<?> clazz, Level level) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger logger = loggerContext.getLogger(clazz);
        logger.setLevel(ch.qos.logback.classic.Level.convertAnSLF4JLevel(level));
    }

    public static void debug(String msgTemp, Object... args) {
        final var logger = getLogger(getCallerClassName());
        if (checkIsEnableForLevel(logger, Level.DEBUG)) {
            final var debugMsg = CharSequenceUtil.format(msgTemp, args);
            logger.debug(debugMsg);
            SpringContextHolder.getBean(LogPostHandlerComposite.class).ifSuccess(handler -> handler.handlerLog(debugMsg, Level.DEBUG));
        }
    }

    public static void info(String msgTemp, Object... args) {
        final var logger = getLogger(getCallerClassName());
        if (checkIsEnableForLevel(logger, Level.INFO)) {
            final var errorMsg = CharSequenceUtil.format(msgTemp, args);
            logger.info(errorMsg);
        }
    }

    public static void warn(String msgTemp, Object... args) {
        final var logger = getLogger(getCallerClassName());
        if (checkIsEnableForLevel(logger, Level.WARN)) {
            final var warnMsg = CharSequenceUtil.format(msgTemp, args);
            logger.warn(warnMsg);
            SpringContextHolder.getBean(LogPostHandlerComposite.class).ifSuccess(handler -> handler.handlerLog(warnMsg, Level.WARN));
        }
    }

    public static void error(String msgTemp, Object... args) {
        final var logger = getLogger(getCallerClassName());
        if (checkIsEnableForLevel(logger, Level.ERROR)) {
            final var errorMsg = CharSequenceUtil.format(msgTemp, args);
            logger.error(errorMsg);
            SpringContextHolder.getBean(LogPostHandlerComposite.class).ifSuccess(handler -> handler.handlerLog(errorMsg, Level.ERROR));
        }
    }

    public static void error(Throwable t, String msgTemp, Object... args) {
        final var logger = getLogger(getCallerClassName());
        if (checkIsEnableForLevel(logger, Level.ERROR)) {
            final var errorMsg = CharSequenceUtil.format(msgTemp, args);
            logger.error(errorMsg, t);
            SpringContextHolder.getBean(LogPostHandlerComposite.class).ifSuccess(handler -> handler.handlerLog(errorMsg, Level.ERROR));
        }
    }


    private static String getCallerClassName() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        // 调用链：getStackTrace<-getCallerClassName <- error/info等方法 <- 业务代码
        if (stackTrace.length >= 4) {
            return stackTrace[3].getClassName();
        }
        return LogUtil.class.getName();
    }

    private static Logger getLogger(String className) {
        return LOGGER_CACHE.computeIfAbsent(className, LoggerFactory::getLogger);
    }

    private static boolean checkIsEnableForLevel(Logger logger, Level level) {
        return logger.isEnabledForLevel(level);
    }

}
